package edu.uoc.tdp.servidor.bbdd.estudiants;

import edu.uoc.tdp.common.EOlympicsException;
import edu.uoc.tdp.bbdd.GestorDiscConnexio;
import edu.uoc.tdp.beans.proves.EstatProva;
import edu.uoc.tdp.beans.proves.PreguntaResposta;
import edu.uoc.tdp.beans.proves.Prova;
import edu.uoc.tdp.beans.proves.Ronda;
import edu.uoc.tdp.beans.proves.RondaEliminatoria;
import edu.uoc.tdp.beans.proves.RondaFinal;
import edu.uoc.tdp.common.EOlympicsExceptionProva;
import edu.uoc.tdp.common.EOlympicsExceptionRonda;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Classe GestorEstudiants
 * TDP Grup 1X4J
 */
public class GestorEstudiants {
    
    private GestorDiscConnexio gestor;
    private Connection connexio;

    /**
     * Constructor de la classe Gestora
     * Crea un nou gestor de disc.
     */
    public GestorEstudiants() throws EOlympicsException {
        this.gestor = new GestorDiscConnexio();
        this.gestor.obreConnexioBD();
        this.connexio = gestor.getConnexio();
    }

    /**
     * Constructor de la classe Gestora
     * Utilitza el gestor de disc passat com a paràmetre
     * @param gdc connexió a la BD de tipus GestorDiscConnexio
     */
    public GestorEstudiants(GestorDiscConnexio gdc) {
        this.gestor   = gdc;
        this.connexio = gdc.getConnexio();
    }
    
    
    //TODO: Definició de mètodes que accedeixen a la BBDD i que es faren servir
    //      des de les implementacions dels objectes Remots
    
    public List<Prova> getProvesInscripcio() throws EOlympicsException{        
        Date avui= new Date(System.currentTimeMillis());        
        String sql="SELECT P.idProva,P.descripcio,P.dataIniInscripcio,P.dataFiInscripcio,P.nombrePlaces "
                + "FROM PROVA P "                
                + "WHERE P.dataIniInscripcio<='"+ avui +"' "
                + "AND P.dataFiInscripcio>='"+ avui +"' "
                + "AND P.estat<> '"  +EstatProva.TANCADA.getEstat() +"' "
                + "AND P.estat<>'"  +EstatProva.CANCELADA.getEstat() +"' ";
        
        return getProves(sql);
    }
    
   private Integer getInscrits(Integer idprova) throws EOlympicsException{   
       
        Statement st=gestor.creaSentencia();
        Integer sortida = 0;
        
        String sql="SELECT count(*) "
                + "FROM INSCRIPCIO I "                
                + "WHERE I.idProva <= " + idprova.toString() ;
        try {
            ResultSet rs=st.executeQuery(sql);
            if(rs.next()){
               sortida = rs.getInt(1);
            } 
        } catch (SQLException sqle){
            treatExceptionSQL(sqle.getMessage());
            
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_DESC_EXEC);
        }                        
        return sortida;
    }
    
    private List<Prova> getProves(String sql) throws EOlympicsException{
        List <Prova>proves= new ArrayList<Prova>();
        Statement st=gestor.creaSentencia();
        Prova prova;
        RondaEliminatoria rondaeliminatoria;
        RondaFinal rondafinal;
        
        try{
            ResultSet rs=st.executeQuery(sql);
            while (rs.next()){  
                
                rondaeliminatoria = new RondaEliminatoria();
                rondafinal = new RondaFinal();
                
                prova = new Prova(rs.getInt(1),rs.getString(2),rs.getDate(3),rs.getDate(4),rs.getInt(5));
                rondaeliminatoria = getRondaEliminatoria(rs.getInt(1));
                rondafinal = getRondaFinal(rs.getInt(1));
                prova.setRondaEliminatoria(rondaeliminatoria);
                prova.setRondaFinal(rondafinal);
                prova.setNombreInscrits(getInscrits(rs.getInt(1)));
                proves.add(prova);
            }
            st.close();
            rs.close();
        }catch (SQLException sqle){
            treatExceptionSQL(sqle.getMessage());
            
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_DESC_EXEC);
        }                        
        return proves;
        
    }
    
    public RondaEliminatoria getRondaEliminatoria(Integer idProva) throws  EOlympicsException{        
       RondaEliminatoria ronda=null;       
        Statement st=gestor.creaSentencia();
        String sql="SELECT R.nombrePreguntes,R.dataIniciRealitzacio,R.dataFiRealitzacio "
                + "FROM RONDA R "                
                + "WHERE R.idProva="+ idProva 
                + " And R.tipusRonda='E'";
        try{
            ResultSet rs=st.executeQuery(sql);
            if (rs.next()){                              
                ronda= new RondaEliminatoria(rs.getInt(1),rs.getDate(2),rs.getDate(3),
                                 getPreguntesRespostesRonda(idProva,"E"));
            }
            st.close();
            rs.close();
        }catch (SQLException sqle){
            System.out.println(sqle.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_SQL);
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_DESC_EXEC);
        }
        
        return ronda;
    }
    
    public RondaFinal getRondaFinal(Integer idProva) throws  EOlympicsException{
       RondaFinal ronda=null;       
        Statement st=gestor.creaSentencia();
        String sql="SELECT R.nombrePreguntes,R.dataIniciRealitzacio,R.dataFiRealitzacio "
                + "FROM RONDA R "                
                + "WHERE R.idProva="+ idProva 
                + " And R.tipusRonda='F'";
        try{
            ResultSet rs=st.executeQuery(sql);
            if (rs.next()){                              
                ronda= new RondaFinal(rs.getInt(1),rs.getDate(2),rs.getDate(3),
                                 getPreguntesRespostesRonda(idProva,"F"));
            }
            st.close();
            rs.close();
        }catch (SQLException sqle){
            System.out.println(sqle.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_SQL);
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_DESC_EXEC);
        }
        
        return ronda;
    }
     /**
     * Accessor de lectura que obté les preguntes i respostes d'una ronda
     * @param idProva               Identificador de la prova
     * @param tipus                 E: Ronda eliminatoria, F: Ronda final
     * @return pr                   Llista de Preguntes i respostes de la ronda
     * @throws EOlympicsExceptionRonda
     * @throws EOlympicsException 
     */
    private List<PreguntaResposta> getPreguntesRespostesRonda(Integer idProva, String tipus) throws EOlympicsExceptionRonda, EOlympicsException{
        List<PreguntaResposta>pr=new ArrayList <PreguntaResposta>();
        Statement st=gestor.creaSentencia();
        String sql="SELECT numPregunta,opcioCorrecta "
                + "FROM RESPOSTACORRECTA "
                + "WHERE idProva="+idProva+" "
                + "AND tipusRonda='"+tipus+"' "
                + "ORDER BY numPregunta";
        try{
            ResultSet rs=st.executeQuery(sql);
            while (rs.next()){
                pr.add(new PreguntaResposta(rs.getInt(1),rs.getString(2)));
            }
        }catch (SQLException sqle){
           treatExceptionSQL(sqle.getMessage());
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new EOlympicsException(EOlympicsException.ERR_DESC_EXEC);
        }
        return pr;
    }
    
    
    private void treatExceptionSQL(String sqle) throws EOlympicsExceptionProva, EOlympicsException{
           if(sqle.contains("pk_prova")) {
               throw new EOlympicsExceptionProva(EOlympicsExceptionProva.ERR_SQL_PK_PROVA);
           }else if(sqle.contains("ck_datainsc")) {
               throw new EOlympicsExceptionProva(EOlympicsExceptionProva.ERR_SQL_CK_PROVA);           
           }
           else{
               System.out.println(sqle);
               throw new EOlympicsException(EOlympicsException.ERR_SQL);
           }
    }

}
